package com.woniuxy.thred.syn;

/**
 * description: UnsafeTest01 <br>
 * date: 2022/2/5 11:55 下午 <br>
 * author: shesaifei <br>
 * version: 1.0 <br>
 */

/**
 * 线程安全：在并发时保证数据的正确性、效率尽可能好
 * synchronized
 * 1、同步方法
 * 2、同步块
 */
public class synBlockTest03 {
    public static void main(String[] args) {
        //一份资源
        SyneWeb123456 web = new SyneWeb123456();
        //多个代理
        System.out.println(Thread.currentThread().getName());
        new Thread(web, "zs").start();
        new Thread(web, "ls").start();
        new Thread(web, "ww").start();
    }
}

class SyneWeb123456 implements Runnable {
    //票数
    private int ticketNums = 10;
    private boolean flag = true;

    @Override
    public void run() {
        while (flag) {
            //模拟延时
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            test5();
        }
    }

    //同步块，线程安全，范围太大--->效率低
    public void test2() {
        synchronized (this) {
            if (ticketNums <= 0) {
                flag = false;
                return;
            }
            //模拟延时
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
        }
    }


    //线程不安全 ticketNums对象在变
    public void test3() {
        synchronized ((Integer) ticketNums) {
            if (ticketNums <= 0) {
                flag = false;
                return;
            }
            //模拟延时
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
        }
    }

    //线程不安全 范围太小锁不住
    public void test4() {
        synchronized (this) {
            if (ticketNums <= 0) {
                flag = false;
                return;
            }
        }
        //模拟延时
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);

    }


    //线程安全：尽可能锁定合理的范围(不是指定代码 指数据的完整性)
    //double checKinng
    public void test5() {
        //考虑的是没有票的情况
        if (ticketNums <= 0) {
            flag = false;
            return;
        }
        synchronized (this) {
            //考虑的是最后一张1票
            if (ticketNums <= 0) {
                flag = false;
                return;
            }
            //模拟延时
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
        }
    }

    //线程安全 同步 锁的是对象资源（this）
    public synchronized void test1() {
        if (ticketNums <= 0) {
            flag = false;
            return;
        }
        //模拟延时
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
    }
}